# -*-coding:utf-8-*-
import tkinter.ttk as ttk
from tkinter.constants import EW, W, X
import tkinter as tk
from tkinter import messagebox
from tkinter.font import Font
import winreg
import ctypes

INTERNET_SETTINGS = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                                   r'Software\Microsoft\Windows\CurrentVersion\Internet Settings',
                                   0, winreg.KEY_ALL_ACCESS)
# 设置刷新
INTERNET_OPTION_REFRESH = 37
INTERNET_OPTION_SETTINGS_CHANGED = 39
internet_set_option = ctypes.windll.Wininet.InternetSetOptionW


def get_proxy():
    # 获取代理信息
    # 如果从来没有开过代理,INTERNET_SETTINGS中存在ProxyEnable键,不存在ProxyOverride和ProxyServer键
    enable, _ = winreg.QueryValueEx(INTERNET_SETTINGS, 'ProxyEnable')
    try:
        override, _ = winreg.QueryValueEx(INTERNET_SETTINGS, 'ProxyOverride')
    except WindowsError:
        override = ''
    try:
        server, _ = winreg.QueryValueEx(INTERNET_SETTINGS, 'ProxyServer')
    except WindowsError:
        server = host = port = ''
    if server:
        host, port = server.split(':')
    return enable, override, host, port


def start_proxy(host, port, override):
    # 启用代理
    # SetValueEx给一个键赋值,键不存在将会自动创建
    try:
        winreg.SetValueEx(INTERNET_SETTINGS, 'ProxyOverride', 0, winreg.REG_SZ, override)
        winreg.SetValueEx(INTERNET_SETTINGS, 'ProxyEnable', 0, winreg.REG_DWORD, 1)
        winreg.SetValueEx(INTERNET_SETTINGS, 'ProxyServer', 0, winreg.REG_SZ, f'{host}:{port}')
        internet_set_option(0, INTERNET_OPTION_REFRESH, 0, 0)
        internet_set_option(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
        return True
    except Exception:
        return False


def stop_proxy():
    # 停用代理
    try:
        winreg.SetValueEx(INTERNET_SETTINGS, 'ProxyEnable', 0, winreg.REG_DWORD, 0)
        internet_set_option(0, INTERNET_OPTION_REFRESH, 0, 0)
        internet_set_option(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
        return True
    except Exception:
        return False


class Application(tk.Tk):
    def __init__(self):
        super().__init__()
        # 调用api设置成由应用程序缩放
        ctypes.windll.shcore.SetProcessDpiAwareness(1)
        # 调用api获得当前的缩放因子
        scale_factor = ctypes.windll.shcore.GetScaleFactorForDevice(0)
        scale = scale_factor / 100
        # 设置缩放因子
        self.tk.call('tk', 'scaling', scale)
        self.title('Windows系统代理设置器')
        self.geometry('{:.0f}x{:.0f}+{}+{}'.format(scale*400, scale*220, 500, 200))
        self.configure(padx=12)
        self.option_add('*Dialog.msg.font', 'SongTi 16')
        self.var_host = tk.StringVar()  # 绑定input_host
        self.var_port = tk.StringVar()  # 绑定input_port
        self.var_enable = tk.IntVar()  # 绑定btn_enable
        self.var_over = tk.StringVar()  # 绑定input_over
        self.create_widgets()
        self.set_input_data()

    def create_widgets(self):
        f1 = Font(family='microsoft yahei', size=16, weight='normal')
        ttk.Style().configure('.', font=f1)  # 设置全局字体
        # ProxyServer相关控件
        frame1 = ttk.Frame(self)
        frame1.pack(fill=X, expand=1)
        frame1.columnconfigure(0, weight=1)
        label_host = ttk.Label(frame1, text='代理ip地址')
        label_host.grid(row=0, column=0, sticky=W)
        label_port = ttk.Label(frame1, text='端口')
        label_port.grid(row=0, column=1, sticky=W)
        self.input_host = ttk.Entry(frame1, textvariable=self.var_host, font=f1)
        self.input_host.grid(row=1, column=0, sticky=EW)
        self.input_port = ttk.Entry(frame1, textvariable=self.var_port, width=12, font=f1)
        self.input_port.grid(row=1, column=1)
        # ProxyOverride相关控件
        frame2 = ttk.Frame(self)
        frame2.pack(fill=X, expand=1)
        label_over = ttk.Label(frame2, text='请勿对以下地址使用代理（多个地址用分号隔离）')
        label_over.pack(anchor=W)
        self.input_over = ttk.Entry(frame2, textvariable=self.var_over, font=f1)
        self.input_over.pack(fill=X)
        # ProxyEnable相关控件
        btn_enable = ttk.Checkbutton(self, text='启用代理服务器', variable=self.var_enable, command=self.click_enable)
        btn_enable.pack(anchor=W, expand=1)
        # 按钮
        frame3 = ttk.Frame(self)
        frame3.pack(fill=X, expand=1)
        frame3.columnconfigure(0, weight=1)
        frame3.columnconfigure(1, weight=1)
        btn_save = ttk.Button(frame3, text='保存', command=self.click_save)
        btn_save.grid(row=0, column=0, sticky=EW, padx=12)
        btn_quit = ttk.Button(frame3, text='退出', command=self.quit)
        btn_quit.grid(row=0, column=1, sticky=EW, padx=12)

    def set_input_data(self):
        enable, override, host, port = get_proxy()
        self.var_host.set(host)
        self.var_port.set(port)
        self.var_over.set(override)
        self.var_enable.set(enable)
        if not enable:
            self.set_input_state('disable')

    def set_input_state(self, s):
        self.input_host.config(state=s)
        self.input_port.config(state=s)
        self.input_over.config(state=s)

    def click_enable(self):
        if self.var_enable.get():
            self.set_input_state('normal')
        else:
            self.set_input_state('disable')

    def click_save(self):
        if self.var_enable.get():
            r = start_proxy(self.var_host.get(), self.var_port.get(), self.var_over.get())
        else:
            r = stop_proxy()
        messagebox.showinfo('提示', '设置成功' if r else'设置失败')


if __name__ == '__main__':
    app = Application()
    app.mainloop()
